"""
负责所有 YouTube API 的交互
"""

import os
import time
import logging
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload

from . import config
import glob
import json

def get_available_channels():
    """扫描tokens文件夹，获取所有可用的YouTube频道"""
    tokens_dir = os.path.join(config.PROJECT_ROOT, "tokens")
    
    channels = []
    
    if not os.path.exists(tokens_dir):
        logging.warning(f"Tokens目录不存在: {tokens_dir}")
        return channels
    
    # 扫描所有token文件
    token_files = glob.glob(os.path.join(tokens_dir, "*_token.json"))
    
    for token_file in token_files:
        try:
            # 从文件名提取频道名称
            filename = os.path.basename(token_file)
            channel_key = filename.replace('_token.json', '')
            channel_name = channel_key.replace('_', ' ').title()
            
            # 验证token文件是否有效
            if os.path.exists(token_file):
                with open(token_file, 'r') as f:
                    token_data = json.load(f)
                    if 'token' in token_data and 'refresh_token' in token_data:
                        channels.append({
                            'key': channel_key,
                            'name': channel_name,
                            'token_file': token_file
                        })
                        logging.info(f"发现有效频道: {channel_name}")
                    else:
                        logging.warning(f"Token文件格式无效: {token_file}")
        except Exception as e:
            logging.error(f"读取token文件失败 {token_file}: {e}")
    
    return channels

def get_authenticated_service(token_file_path=None):
    """通过 OAuth 2.0 认证并返回 YouTube API 服务对象。
    
    Args:
        token_file_path: 指定的token文件路径，如果为None则使用默认配置
    """
    SCOPES = ['https://www.googleapis.com/auth/youtube.upload', 'https://www.googleapis.com/auth/youtube.force-ssl']
    credentials = None

    # 使用指定的token文件路径或默认配置
    if token_file_path:
        token_file = token_file_path
    else:
        token_file = config.YOUTUBE_API_TOKEN_FILE
    
    secret_file = config.YOUTUBE_API_SECRETS_FILE

    if os.path.exists(token_file):
        credentials = Credentials.from_authorized_user_file(token_file, SCOPES)

    if not credentials or not credentials.valid:
        if credentials and credentials.expired and credentials.refresh_token:
            credentials.refresh(Request())
        else:
            if not os.path.exists(secret_file):
                raise FileNotFoundError(f"客户端密钥文件不存在: {secret_file}")
            flow = InstalledAppFlow.from_client_secrets_file(secret_file, SCOPES)
            credentials = flow.run_local_server(port=0)
        with open(token_file, "w") as token:
            token.write(credentials.to_json())
    
    return build("youtube", "v3", credentials=credentials)

def upload_video_to_youtube(**kwargs):
    """
    上传视频到 YouTube，支持定时发布、添加播放列表和自定义封面。
    """
    logging.info("准备上传视频到 YouTube...")
    
    # 获取指定频道的认证服务
    token_file_path = kwargs.get('token_file_path')
    youtube = get_authenticated_service(token_file_path)

    request_body = {
        "snippet": {
            "title": kwargs['title'], "description": kwargs['description'],
            "tags": kwargs['tags'], "categoryId": kwargs['category_id']
        },
        "status": {"privacyStatus": kwargs['privacy'], "madeForKids": kwargs.get('made_for_kids', False)}
    }
    if kwargs.get('publish_at') and kwargs['privacy'] in ["private", "unlisted"]:
        request_body["status"]["publishAt"] = kwargs['publish_at']

    media = MediaFileUpload(kwargs['file_path'], mimetype="video/mp4", resumable=True)
    request = youtube.videos().insert(part="snippet,status", body=request_body, media_body=media)
    
    response = None
    retry = 0
    while response is None:
        try:
            status, response = request.next_chunk()
            if status:
                logging.info(f"上传进度: {int(status.progress() * 100)}%")
        except Exception as e:
            if retry < 3:
                retry += 1
                logging.warning(f"上传中断，正在重试 ({retry}/3)...\n错误: {e}")
                time.sleep(5)
            else:
                logging.error("上传失败，已达最大重试次数。")
                return

    video_id = response.get('id')
    logging.info(f"视频已上传: https://www.youtube.com/watch?v={video_id}")

    if kwargs.get('playlist'):
        youtube.playlistItems().insert(part="snippet", body={
            "snippet": {"playlistId": kwargs['playlist'], "resourceId": {"kind": "youtube#video", "videoId": video_id}}
        }).execute()
        logging.info(f"视频已添加到播放列表。")

    if kwargs.get('thumbnail_path'):
        youtube.thumbnails().set(videoId=video_id, media_body=MediaFileUpload(kwargs['thumbnail_path'])).execute()
        logging.info("自定义封面已设置。")

def upload_to_youtube(output_path: str, base_name: str, chapters: str, video_summary: str, video_keywords: list, 
                     custom_title: str = None, thumbnail_path: str = None, privacy_status: str = "private", 
                     made_for_kids: bool = False, selected_channel: str = None):
    """将增强后的视频上传到 YouTube。"""
    logging.info("准备上传视频到 YouTube...")

    # 使用自定义标题或默认标题
    if custom_title and custom_title.strip():
        video_title = custom_title.strip()
        logging.info(f"使用自定义标题: {video_title}")
    else:
        video_title = base_name.replace("_original", "").replace("_", " ").strip()
        logging.info(f"使用默认标题: {video_title}")

    if chapters:
        video_description = f"{chapters}\n\n{video_summary}\n\n这是一个由 AI 增强的视频。\n更多精彩内容，敬请关注！"
    else:
        video_description = f"{video_summary}\n\n这是一个由 AI 增强的视频。\n更多精彩内容，敬请关注！"

    logging.info(f"最终视频描述:\n---\n{video_description}\n---")

    final_video_tags = video_keywords if video_keywords else ["AI", "视频增强", "双语字幕", "知识卡片", "YouTube自动化"]

    video_category_id = "27"
    # 使用传入的隐私设置和儿童内容设置
    logging.info(f"视频将以 '{privacy_status}' 模式上传")
    logging.info(f"儿童内容设置: {'是' if made_for_kids else '否'}")

    try:
        # 查找选定频道的token文件
        token_file_path = None
        if selected_channel:
            available_channels = get_available_channels()
            for channel in available_channels:
                if channel['key'] == selected_channel:
                    token_file_path = channel['token_file']
                    logging.info(f"使用频道: {channel['name']} (Token: {token_file_path})")
                    break
            
            if not token_file_path:
                logging.error(f"未找到选定频道的token文件: {selected_channel}")
                raise Exception(f"未找到频道 '{selected_channel}' 的token文件")
        
        upload_params = {
            "file_path": output_path,
            "title": video_title,
            "description": video_description,
            "tags": final_video_tags,
            "category_id": video_category_id,
            "privacy": privacy_status,
            "made_for_kids": made_for_kids,
            "token_file_path": token_file_path
        }
        
        # 如果有自定义封皮，添加到参数中
        if thumbnail_path and os.path.exists(thumbnail_path):
            upload_params["thumbnail_path"] = thumbnail_path
            logging.info(f"将使用自定义封皮: {thumbnail_path}")
        
        upload_video_to_youtube(**upload_params)
    except Exception as e:
        logging.error(f"视频上传到 YouTube 失败: {e}")
